﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace NickPowell.LiveCode
{
    public partial class LiveCode : UserControl
    {
        private struct ProjectInfo
        {
            public int iID;
            public string sName;

            public ProjectInfo(int id, string name)
            {
                this.iID = id;
                this.sName = name;
            }

            public override string ToString()
            {
                return this.sName;
            }
        }

        private MyToolWindow toolWindow;

        private User user;

        public LiveCode(MyToolWindow _toolWindow)
        {
            this.toolWindow = _toolWindow;
            this.user = new User(this);

            InitializeComponent();

            this.pnlLogin.Visible = true;
            this.pnlProjectSelect.Visible = false;
            this.pnlChat.Visible = false;

            this.pnlProjectSelect.Location = new Point(3, 3);
            this.pnlChat.Location = new Point(3, 3);

            this.pnlChat.Dock = DockStyle.Fill;
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
            try
            {
                if (!String.IsNullOrEmpty(this.tbUsername.Text) && !String.IsNullOrEmpty(this.tbPassword.Text))
                {
                    if (this.user.Login(this.tbUsername.Text, this.tbPassword.Text))
                    {
                        //MessageBox.Show("Login succeeded");
                        foreach(KeyValuePair<int, string> project in this.user.UserProjects)
                        {
                            ProjectInfo proj = new ProjectInfo(project.Key, project.Value);
                            this.lbProjects.Items.Add(proj);
                        }

                        this.pnlLogin.Visible = false;
                        this.pnlProjectSelect.Visible = true;
                    }
                    else
                    {
                        MessageBox.Show("Login Failed");
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void btnSelectProject_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.lbProjects.SelectedItem != null)
                {
                    int iProjectID = ((ProjectInfo)this.lbProjects.SelectedItem).iID;

                    this.user.ProjectLogin(iProjectID);

                    this.pnlChat.Size = this.Size;

                    this.pnlChat.Visible = true;
                    this.pnlProjectSelect.Visible = false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void tbUsername_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.btnLogin_Click(new object(), new EventArgs());
            }
        }

        private void tbPassword_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.btnLogin_Click(new object(), new EventArgs());
            }
        }

        private delegate void LogoffCallback();

        public void Logoff()
        {
            try
            {
                if (this.InvokeRequired)
                {
                    if (this.InvokeRequired)
                    {
                        LogoffCallback callback = new LogoffCallback(Logoff);
                        this.Invoke(callback, new object[] { });
                        return;
                    }
                }

                this.tbPassword.Text = "";

                this.pnlLogin.Visible = true;
                this.pnlProjectSelect.Visible = false;
                this.pnlChat.Visible = false;

                this.lbProjects.Items.Clear();
                this.lvUsers.Items.Clear();
                this.tcMessages.TabPages.Clear();

                this.user.IOHandler.DisconnectFromServer();

                this.user = new User(this);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        private void btnLogoff_Click(object sender, EventArgs e)
        {
            this.Logoff();
        }

        #region Chat
        private delegate void ChatUserLogonCallback(int iID, string sName);

        public void ChatUserLogon(int iID, string sName)
        {
            if (this.InvokeRequired)
            {
                if (this.InvokeRequired)
                {
                    ChatUserLogonCallback callback = new ChatUserLogonCallback(ChatUserLogon);
                    this.Invoke(callback, new object[] { iID, sName });
                    return;
                }
            }

            if (!this.lvUsers.Items.ContainsKey(iID.ToString()))
            {
                this.lvUsers.Items.Add(iID.ToString(), sName, null);
            }
        }

        private delegate void ChatUserLogoffCallback(int iID);

        public void ChatUserLogoff(int iID)
        {
            if (this.InvokeRequired)
            {
                if (this.InvokeRequired)
                {
                    ChatUserLogoffCallback callback = new ChatUserLogoffCallback(ChatUserLogoff);
                    this.Invoke(callback, new object[] { iID });
                    return;
                }
            }

            if (this.lvUsers.Items.ContainsKey(iID.ToString()))
            {


                this.lvUsers.Items.RemoveByKey(iID.ToString());
            }
        }

        private delegate void ChatMessageCallback(int iFromID, string sText);

        public void ChatMessage(int iFromID, string sText)
        {
            try
            {
                if (this.InvokeRequired)
                {
                    if (this.InvokeRequired)
                    {
                        ChatMessageCallback callback = new ChatMessageCallback(ChatMessage);
                        this.Invoke(callback, new object[] { iFromID, sText });
                        return;
                    }
                }

                //Check if there is already an open message tab
                if (this.tcMessages.TabPages.ContainsKey(iFromID.ToString()))
                {
                    TabPage messageTab = this.tcMessages.TabPages[iFromID.ToString()];
                    string sFromName = this.lvUsers.Items[iFromID.ToString()].Text;

                    ListBox lbMessage = ((ListBox)(((SplitContainer)messageTab.Controls["messageContainer"]).Panel1.Controls["lbMessage"]));
                    lbMessage.Items.Add(sFromName + ": " + sText);
                    int itemsPerPage = (int)(lbMessage.Height / lbMessage.ItemHeight);
                    lbMessage.TopIndex = lbMessage.Items.Count - itemsPerPage;
                }
                else
                {
                    string sFromName = this.lvUsers.Items[iFromID.ToString()].Text;

                    TabPage messageTab = new TabPage(sFromName);
                    messageTab.Name = iFromID.ToString();

                    ListBox lbMessage = new ListBox();
                    lbMessage.Name = "lbMessage";
                    lbMessage.Dock = System.Windows.Forms.DockStyle.Fill;
                    lbMessage.FormattingEnabled = true;
                    lbMessage.HorizontalScrollbar = true;
                    lbMessage.Location = new System.Drawing.Point(0, 0);
                    lbMessage.Size = new System.Drawing.Size(403, 121);

                    lbMessage.Items.Add(sFromName + ": " + sText);

                    TextBox tbText = new TextBox();
                    tbText.Name = "tbText";
                    tbText.Dock = System.Windows.Forms.DockStyle.Fill;
                    tbText.Location = new System.Drawing.Point(0, 0);
                    tbText.Multiline = true;
                    tbText.Size = new System.Drawing.Size(403, 66);
                    tbText.KeyDown += new KeyEventHandler(tbText_KeyDown);

                    SplitContainer messageContainer = new SplitContainer();
                    messageContainer.Name = "messageContainer";
                    messageContainer.Dock = System.Windows.Forms.DockStyle.Fill;
                    messageContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
                    messageContainer.IsSplitterFixed = true;
                    messageContainer.Location = new System.Drawing.Point(0, 0);
                    messageContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;

                    messageContainer.Panel1.Controls.Add(lbMessage);

                    messageContainer.Panel2.Controls.Add(tbText);

                    messageContainer.Size = new System.Drawing.Size(403, 191);
                    messageContainer.SplitterDistance = 140;

                    messageTab.Controls.Add(messageContainer);

                    this.tcMessages.TabPages.Add(messageTab);
                    messageTab.Focus();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        private void lvUsers_DoubleClick(object sender, EventArgs e)
        {
            //Create a new message tab to the selected user
            if (this.lvUsers.SelectedItems.Count== 1)
            {
                int iUserID = int.Parse(this.lvUsers.SelectedItems[0].Name);
                string sName = this.lvUsers.SelectedItems[0].Text;

                this.NewMessageWindow(iUserID, sName);
            }
        }

        private void NewMessageWindow(int iUserID, string sName)
        {
            try
            {
                //Check if there is already an open message tab
                if (this.tcMessages.TabPages.ContainsKey(iUserID.ToString()))
                {
                    TabPage messageTab = this.tcMessages.TabPages[iUserID.ToString()];
                    messageTab.Focus();
                }
                else
                {
                    TabPage messageTab = new TabPage(sName);
                    messageTab.Name = iUserID.ToString();

                    ListBox lbMessage = new ListBox();
                    lbMessage.Name = "lbMessage";
                    lbMessage.Dock = System.Windows.Forms.DockStyle.Fill;
                    lbMessage.FormattingEnabled = true;
                    lbMessage.HorizontalScrollbar = true;
                    lbMessage.Location = new System.Drawing.Point(0, 0);
                    lbMessage.Size = new System.Drawing.Size(403, 121);

                    TextBox tbText = new TextBox();
                    tbText.Name = "tbText";
                    tbText.Dock = System.Windows.Forms.DockStyle.Fill;
                    tbText.Location = new System.Drawing.Point(0, 0);
                    tbText.Multiline = true;
                    tbText.Size = new System.Drawing.Size(403, 66);
                    tbText.KeyDown += new KeyEventHandler(tbText_KeyDown);

                    SplitContainer messageContainer = new SplitContainer();
                    messageContainer.Name = "messageContainer";
                    messageContainer.Dock = System.Windows.Forms.DockStyle.Fill;
                    messageContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
                    messageContainer.IsSplitterFixed = true;
                    messageContainer.Location = new System.Drawing.Point(0, 0);
                    messageContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;

                    messageContainer.Panel1.Controls.Add(lbMessage);

                    messageContainer.Panel2.Controls.Add(tbText);

                    messageContainer.Size = new System.Drawing.Size(403, 191);
                    messageContainer.SplitterDistance = 140;

                    messageTab.Controls.Add(messageContainer);

                    this.tcMessages.TabPages.Add(messageTab);
                    messageTab.Focus();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        void tbText_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyCode == Keys.Enter)
                {
                    int iUserID = int.Parse(((TabPage)((TextBox)sender).Parent.Parent.Parent).Name);
                    string sText = ((TextBox)sender).Text;

                    ListBox lbMessage = ((ListBox)((SplitContainer)(((TextBox)sender).Parent.Parent)).Panel1.Controls["lbMessage"]);
                    lbMessage.Items.Add("You: " + sText);
                    int itemsPerPage = (int)(lbMessage.Height / lbMessage.ItemHeight);
                    lbMessage.TopIndex = lbMessage.Items.Count - itemsPerPage;

                    ((TextBox)sender).Text = "";

                    this.user.SendChatMessage(iUserID, sText);

                    e.SuppressKeyPress = true;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void LiveCode_SizeChanged(object sender, EventArgs e)
        {
            if (this.pnlChat.Visible)
            {
                this.pnlChat.Size = this.Size;
            }
        }
        #endregion
    }
}
